package utils

import (
	"fmt"
	"reflect"
	"sort"
	"strings"
	"sync"
	"time"
)

/*
*
k=v;k=v
*/
func KvMapWrite(str string, kv *GSyncMapGroup) (ip string, port int) {
	strs := strings.Split(str, ";")
	for i := 0; i < len(strs); i++ {
		k, v := Split2Str(strs[i], "=")
		kv.Set(k, v)
	}
	return
}

func SliceIndexByte(lst []byte, v byte) int {
	for i := 0; i < len(lst); i++ {
		if lst[i] == v {
			return i
		}
	}
	return -1
}

func Strlst2Num3(strs ...string) (n1, n2, n3 float64) {
	if len(strs) == 0 {
		return
	}
	n1 = StrToFloat64Def(strs[0], 0)
	if len(strs) > 1 {
		n2 = StrToFloat64Def(strs[1], 0)
		if len(strs) > 2 {
			n3 = StrToFloat64Def(strs[2], 0)
		}
	}
	return
}

func Str2Num3Ex(str, sep string) (n1, n2, n3 float64) {
	strs := strings.SplitN(str, sep, 3)
	n1 = StrToFloat64Def(strs[0], 0)
	if len(strs) > 1 {
		n2 = StrToFloat64Def(strs[1], 0)
		if len(strs) > 2 {
			n3 = StrToFloat64Def(strs[2], 0)
		}
	}
	return
}

func Str2Num3(str string) (n1, n2, n3 float64) {
	str = strings.ReplaceAll(str, "\r", " ")
	str = strings.ReplaceAll(str, "\n", " ")
	str = strings.ReplaceAll(str, "\t", " ")
	str = strings.ReplaceAll(str, ",", " ")
	str = strings.ReplaceAll(str, ";", " ")
	str = ReplaceMultiSpace2One(str, " ")
	strs := strings.SplitN(str, " ", 3)
	n1 = StrToFloat64Def(strs[0], 0)
	if len(strs) > 1 {
		n2 = StrToFloat64Def(strs[1], 0)
		if len(strs) > 2 {
			n3 = StrToFloat64Def(strs[2], 0)
		}
	}
	return
}

func AppendSliceSorted(lst []interface{}, v interface{}, lessfunc func(m, v interface{}) bool) []interface{} {
	n := len(lst)
	i := sort.Search(n, func(i int) bool {
		return lessfunc(lst[i], v)
	})
	if i == n {
		return append(lst, v)
	}
	// we now know that i points at where we want to insert
	lst = append(lst, nil)   // try to grow the slice in place, any entry works.
	copy(lst[i+1:], lst[i:]) // Move shorter entries down
	lst[i] = v
	return lst
}

func StrArray2Vars(src []string) []interface{} {
	rval := make([]interface{}, len(src))
	for i := 0; i < len(src); i++ {
		rval[i] = src[i]
	}
	return rval
}

func IndexInt(v int, lst ...int) int {
	for i := 0; i < len(lst); i++ {
		if lst[i] == v {
			return i
		}
	}
	return -1
}

func SliceIndexInt(lst []int, v int) int {
	for i := 0; i < len(lst); i++ {
		if lst[i] == v {
			return i
		}
	}
	return -1
}

func SliceIndexStr(lst []string, v string) int {
	for i := 0; i < len(lst); i++ {
		if lst[i] == v {
			return i
		}
	}
	return -1
}

/* 在slice中去除重复的元素，其中a必须是已经排序的序列。
 * params:
 *   a: slice对象，如[]string, []int, []float64, ...
 * return:
 *   []interface{}: 已经去除重复元素的新的slice对象
 */
func SliceRemoveDuplicate(a interface{}) (ret []interface{}) {
	if reflect.TypeOf(a).Kind() != reflect.Slice {
		fmt.Printf("<SliceRemoveDuplicate> <a> is not slice but %T\n", a)
		return ret
	}

	va := reflect.ValueOf(a)
	for i := 0; i < va.Len(); i++ {
		if i > 0 && reflect.DeepEqual(va.Index(i-1).Interface(), va.Index(i).Interface()) {
			continue
		}
		ret = append(ret, va.Index(i).Interface())
	}

	return ret
}

/*
**

	用协程执行fn 超时返回
	false: 非正常结束
*/
func ExecTimeOut(fn func(), timeout time.Duration) bool {
	wt := NewWaitWithTimeout()
	wt.Add(1)
	go func() {
		fn()
		wt.Done()
	}()
	return wt.WaitFor(timeout)
}

// / 192.0.2.1:25
// [2001:db8::1]:80
func ExtractIpAndPort(addr string) (ip string, port int) {
	n := strings.LastIndex(addr, ":")
	ip = string([]byte(addr)[:n])
	port = StrToIntDef(string([]byte(addr)[n+1:]), 0)
	return
}

///**  使用WaitWithTimeOut
//  @result
//    true: 等待完成信号
//    false: 超时信号
//*/
//func WaitFor(wait *sync.WaitGroup, timeout time.Duration) bool {
//	ch := make(chan bool)
//	go func() {
//		wait.Wait()
//		ch <- false
//	}()
//	select {
//	case <-ch:
//		return true
//	case <-time.After(timeout):
//		return false
//	}
//
//}

func SyncMapLength(amap *sync.Map) int {
	r := 0
	amap.Range(func(key, value interface{}) bool {
		r++
		return true
	})
	return r
}

/***
 * -1: 未找到
 * v和slice中的元素的类型需要相同
 */
func SliceIndex(list interface{}, v interface{}) int {
	va := reflect.ValueOf(list)
	for i := 0; i < va.Len(); i++ {
		v0 := va.Index(i).Interface()
		if reflect.DeepEqual(v0, v) {
			return i
		}
	}
	return -1
}

func SliceStrCopy(src []string) []string {
	if src == nil {
		return nil
	}
	rval := make([]string, len(src))
	copy(rval, src)
	return rval
}

/***
 * 如果不存在 返回 原有的
 */
func SliceStrRemove(src []string, ele string) ([]string, bool) {
	if src == nil {
		return src, false
	}
	idx := SliceIndex(src, ele)
	if idx == -1 {
		return src, false
	}
	return SliceStrDelete(src, idx)
}

func SliceStrDelete(src []string, idx int) ([]string, bool) {
	if src == nil {
		return src, false
	}

	if idx < 0 {
		return src, false
	}

	if idx >= len(src) {
		return src, false
	}

	rval := append(src[:idx], src[idx+1:]...)
	return rval, true
}

func NewSyncPool(newFunc func() interface{}) *sync.Pool {
	pool := new(sync.Pool)
	if newFunc != nil {
		pool.New = newFunc
	}
	return pool
}
